﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
namespace Quick.CodeGenerator
{
    public partial class MainFrm : Form
    {
        Data.DbInfo m_DbInfoDal = null;
        public MainFrm()
        {
            InitializeComponent();
            m_DbInfoDal = new Data.DbInfo();
        }

        private void MainFrm_Load(object sender, EventArgs e)
        {
            LoadDbInfos();
        }
        /// <summary>
        /// 加载节点
        /// </summary>
        private void LoadDbInfos()
        {
            Action action = () =>
            {
                tvDBList.Nodes.Clear();
                List<Model.DbInfo> dbInfos = m_DbInfoDal.GetList();
                if (null != dbInfos && dbInfos.Count > 0)
                {
                    dbInfos = dbInfos.OrderBy(t => t.DbType).ThenBy(t => t.DbName).ToList();
                    List<string> dbTypes = dbInfos.Select(t => t.DbType).Distinct().ToList();
                    for (int i = 0; i < dbTypes.Count; i++)
                    {
                        TreeNode tn = new TreeNode(dbTypes[i]);
                        tn.ForeColor = Color.Blue;
                        tn.Tag = "DataBaseType";
                        tn.Text = tn.Text;
                        List<Model.DbInfo> cTreeNodes = dbInfos.Where(t => dbTypes[i].Equals(t.DbType, StringComparison.OrdinalIgnoreCase)).ToList();
                        for (int j = 0; j < cTreeNodes.Count; j++)
                        {
                            TreeNode cTn = new TreeNode(cTreeNodes[j].DbName);
                            cTn.Tag = cTreeNodes[j];
                            tn.Nodes.Add(cTn);
                        }
                        tvDBList.Nodes.Add(tn);
                    }
                }
            };

            if (tvDBList.InvokeRequired)
            {
                tvDBList.BeginInvoke(action);
            }
            else
            {
                action();
            }
        }
        /// <summary>
        /// 获取数据库链接对象
        /// </summary>
        /// <returns></returns>
        private Data.IDataBase GetDataBase()
        {
            var assembly = Assembly.GetExecutingAssembly();
            var dbInfo = tvDBList.SelectedNode.Tag as Model.DbInfo;
            if (null == dbInfo)
            {
                MessageBox.Show("请先选择需要查询的数据库!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return null;
            }
            Data.IDataBase db = assembly.CreateInstance("Quick.CodeGenerator.Data." + dbInfo.DbType, true) as Data.IDataBase;
            db.SetConnection(dbInfo.DbConnectionString);
            return db;
        }
        /// <summary>
        /// 树形结构 节点选择变更
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tvDBList_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if ("DataBaseType".Equals(Convert.ToString(e.Node.Tag), StringComparison.OrdinalIgnoreCase))
            {   //顶级节点,不管
                splitContainer2.Enabled = false;
                return;
            }
            splitContainer2.Enabled = true;
        }
        /// <summary>
        /// 全选按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void chkAll_CheckedChanged(object sender, EventArgs e)
        {
            if (lvTable.Items.Count > 0)
            {
                for (int i = 0; i < lvTable.Items.Count; i++)
                {
                    lvTable.Items[i].Checked = chkAll.Checked;
                }
            }
        }
        private void btnSearch_Click(object sender, EventArgs e)
        {
            Data.IDataBase db = GetDataBase();
            if (null == db)
            {
                return;
            }
            var list = db.GetTableListInfo(txtKeywords.Text.ToUpper());
            lvTable.Items.Clear();
            if (null == list || list.Count == 0)
            {
                MessageBox.Show("未能查找到任何数据!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            for (int i = 0; i < list.Count; i++)
            {
                ListViewItem lvi = new ListViewItem(list[i].TableName);
                lvi.SubItems.AddRange(new string[] { list[i].TableType });
                lvTable.Items.Add(lvi);
            }
            lvTable.Refresh();
        }
        /// <summary>
        /// table 选择项变更
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lvTable_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lvTable.SelectedItems.Count == 0)
            {
                return;
            }
            var tableName = lvTable.SelectedItems[0].Text;
            Data.IDataBase db = GetDataBase();
            if (null == db)
            {
                return;
            }
            List<Model.ColumnInfo> list = db.GetColumnInfoList(tableName);
            lvColInfo.Items.Clear();
            if (null == list || list.Count == 0)
            {
                MessageBox.Show("未能查找到任何数据!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            var setting = GetSetting();
            setting.HasEntityNamespace = true;
            setting.HasRepositoryNamespace = true;
            setting.HasContractsNamespace = true;
            setting.HasIServicesNamespace = true;
            setting.HasServicesNamespace = true;
            Generator.Process.Instance.Execute2String(setting, GetDataBase(), tableName, ShowCodeTemplate);

            for (int i = 0; i < list.Count; i++)
            {
                ListViewItem lvi = new ListViewItem(list[i].COLUMN_NAME);
                lvi.SubItems.AddRange(new string[] { list[i].CONSTRAINT_TYPE??"",
                                                     list[i].DATA_TYPE??"",
                                                     list[i].DATA_LENGTH??"",
                                                     list[i].DATA_PRECISION??"",
                                                     list[i].DATA_SCALE??"",
                                                     list[i].NULLABLE??"",
                                                     list[i].DATA_DEFAULT??"",
                                                     list[i].COMMENTS??"",
                                                     list[i].TABLE_NAME??""});
                lvColInfo.Items.Add(lvi);
            }
            lvColInfo.Refresh();
        }
        /// <summary>
        /// 显示模版代码
        /// </summary>
        /// <param name="cts"></param>
        private void ShowCodeTemplate(Model.CodeTemplateString cts)
        {
            Action action = () => 
            {
                rtbModel.Text = cts.ModelTemplateString;
                rtbIData.Text = cts.IDataTemplateString;
                rtbData.Text = cts.DataTemplateString;
                rtbIServices.Text = cts.IServicesTemplateString;
                rtbServices.Text = cts.ServicesTemplateString;
                rtbVueJson.Text = cts.VueJsonTemplateString;
                rtbDb2Model.Text = cts.Db2ModelTemplateString;
            };
            if (rtbModel.InvokeRequired)
            {
                rtbModel.BeginInvoke(action, null);
            }
            else
            {
                action();
            }
        }
        /// <summary>
        /// 浏览文件夹
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnFolder_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog fbd = new FolderBrowserDialog();
            fbd.Description = "请选择代码生成存储路径";
            if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                if (string.IsNullOrEmpty(fbd.SelectedPath))
                {
                    MessageBox.Show(this, "文件夹路径不能为空", "提示");
                    return;
                }
                txtFolder.Text = fbd.SelectedPath;
            }
        }

        private void tsmi_ConnectionDB_Click(object sender, EventArgs e)
        {
            ModifyConnectionFrm frm = new ModifyConnectionFrm(ModifyTreeView);
            frm.ShowDialog();
        }
        /// <summary>
        /// 刷新
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsmi_Refresh_Click(object sender, EventArgs e)
        {
            string id = string.Empty;
            Model.DbInfo dbInfo = null;
            if (tvDBList.SelectedNode != null)
            {
                dbInfo = tvDBList.SelectedNode.Tag as Model.DbInfo;
                if (dbInfo != null)
                {
                    id = dbInfo.ID;
                    ModifyTreeView("Update", id);
                    return;
                }
            }
            ModifyTreeView("Add", "");
        }
        /// <summary>
        /// 右键菜单,编辑
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsmi_Edit_Click(object sender, EventArgs e)
        {
            var tn = tvDBList.SelectedNode;
            if (null == tn || "DataBaseType".Equals(Convert.ToString(tn.Tag), StringComparison.OrdinalIgnoreCase))
            {
                MessageBox.Show("请选择需要编辑的数据库信息", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            Model.DbInfo dbInfo = tn.Tag as Model.DbInfo;
            ModifyConnectionFrm frm = new ModifyConnectionFrm(dbInfo, ModifyTreeView);
            frm.ShowDialog();
        }
        /// <summary>
        /// 右键菜单,删除
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsmi_Delete_Click(object sender, EventArgs e)
        {
            Data.DbInfo m_DbInfoDal = new Data.DbInfo();
            var tn = tvDBList.SelectedNode;
            if (null == tn || "DataBaseType".Equals(Convert.ToString(tn.Tag), StringComparison.OrdinalIgnoreCase))
            {
                MessageBox.Show("请选择需要编辑的数据库信息", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            if (MessageBox.Show("确定删除选中项?", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK)
            {
                Model.DbInfo dbInfo = tn.Tag as Model.DbInfo;
                m_DbInfoDal.Delete(dbInfo);
                ModifyTreeView("Delete", dbInfo.ID);
            }
        }


        /// <summary>
        /// 根据操作处理TreeView数据
        /// </summary>
        /// <param name="op"></param>
        /// <param name="id"></param>
        private void ModifyTreeView(string op, string id)
        {
            Action action = () =>
            {
                bool isSelect = false;
                for (int i = 0; i < tvDBList.Nodes.Count && isSelect == false; i++)
                {
                    var nodes = tvDBList.Nodes[i].Nodes;
                    if (nodes != null && nodes.Count > 0)
                    {
                        for (int j = 0; j < nodes.Count; j++)
                        {
                            var node = nodes[j];
                            var dbInfo = node.Tag as Model.DbInfo;
                            if (null != dbInfo && dbInfo.ID.Equals(id, StringComparison.OrdinalIgnoreCase))
                            {
                                tvDBList.SelectedNode = node;
                                isSelect = true;
                                break;
                            }
                        }
                    }
                }
            };
            LoadDbInfos();

            if ("Update".Equals(op, StringComparison.OrdinalIgnoreCase))
            {
                if (tvDBList.InvokeRequired)
                {
                    tvDBList.BeginInvoke(action);
                }
                else
                {
                    action();
                }
            }
        }
        /// <summary>
        /// 显示处理进度
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="percent"></param>
        private void ShowProcessProgress(string msg, double percent)
        {
            Action action = () =>
            {
                tspbPercent.Value = Convert.ToInt32(percent * 100);
                tsslMsg.Text = msg;
                tsslPercent.Text = Convert.ToString(percent) + "%";
            };
            if (statusStrip1.InvokeRequired)
            {
                statusStrip1.BeginInvoke(action);
            }
            else
            {
                action();
            }
        }
        #region 代码生成器
        /// <summary>
        /// 获取面板配置信息
        /// </summary>
        /// <returns></returns>
        private Model.CodeGeneratorSetting GetSetting()
        {
            Model.CodeGeneratorSetting setting = new Model.CodeGeneratorSetting();
            setting.TableNames = GetSelectTableList();
            
            #region 项目属性配置
            setting.Project = txtProjectName.Text.Trim();
            setting.EntityNamespace = txtModelNamespace.Text.Trim();
            setting.ContractsNamespace = txtIDataNamespace.Text.Trim();
            setting.RepositoryNamespace = txtDataNamespace.Text.Trim();
            setting.IServicesNamespace = txtIServicesNamespace.Text.Trim();
            setting.ServicesNamespace = txtServicesNamespace.Text.Trim();
            #endregion

            #region 代码模版配置
            setting.Creator = txtCreator.Text.Trim();
            setting.DbConnectionStringName = txtDbConnectionStrings.Text.Trim();
            setting.HasSoftDelete = chkIsSoftDelete.Checked;
            setting.SoftDeleteColumn = txtSoftDelete.Text.Trim();
            setting.SoftDeleteEfficacious = txtSoftDeleteEfficacious.Text.Trim();
            setting.SoftDeleteInvalid = txtSoftDeleteInvalid.Text.Trim();
            setting.SavePath = txtFolder.Text;
            #endregion
            return setting;
        }
        /// <summary>
        /// 获取勾选的table列表
        /// </summary>
        /// <returns></returns>
        private List<string> GetSelectTableList()
        {
            List<string> list = new List<string>();
            for (int i = 0; i < lvTable.Items.Count; i++)
            {
                if (lvTable.Items[i].Checked)
                {
                    list.Add(lvTable.Items[i].Text);
                }
            }
            return list;
        }
        #endregion

        #region 执行代码生成
        private void btnModel_Click(object sender, EventArgs e)
        {
            try
            {
                DeleteAllFiles();
                var setting = GetSetting();
                setting.HasEntityNamespace = true;
                Generator.Process.Instance.Execute(setting, GetDataBase(), ShowProcessProgress);
            }
            catch (Exception ex)
            {
                MessageBox.Show("生成*.cs出现异常:" + ex.Message, "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        private void btnIData_Click(object sender, EventArgs e)
        {
            try
            {
                DeleteAllFiles();
                var setting = GetSetting();
                setting.HasContractsNamespace = true;
                Generator.Process.Instance.Execute(setting, GetDataBase(), ShowProcessProgress);
            }
            catch (Exception ex)
            {
                MessageBox.Show("生成*.cs出现异常:" + ex.Message, "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        private void btnData_Click(object sender, EventArgs e)
        {
            try
            {
                DeleteAllFiles();
                var setting = GetSetting();
                setting.HasRepositoryNamespace = true;
                Generator.Process.Instance.Execute(setting, GetDataBase(), ShowProcessProgress);
            }
            catch (Exception ex)
            {
                MessageBox.Show("生成*.cs出现异常:" + ex.Message, "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        private void btnIServices_Click(object sender, EventArgs e)
        {
            try
            {
                DeleteAllFiles();
                var setting = GetSetting();
                setting.HasIServicesNamespace = true;
                Generator.Process.Instance.Execute(setting, GetDataBase(), ShowProcessProgress);
            }
            catch (Exception ex)
            {
                MessageBox.Show("生成*.cs出现异常:" + ex.Message, "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        private void btnServices_Click(object sender, EventArgs e)
        {
            try
            {
                DeleteAllFiles();
                var setting = GetSetting();
                setting.HasServicesNamespace = true;
                Generator.Process.Instance.Execute(setting, GetDataBase(), ShowProcessProgress);
            }
            catch (Exception ex)
            {
                MessageBox.Show("生成*.cs出现异常:" + ex.Message, "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        private void btnAll_Click(object sender, EventArgs e)
        {
            try
            {
                DeleteAllFiles();
                var setting = GetSetting();
                setting.HasEntityNamespace = true;
                setting.HasRepositoryNamespace = true;
                setting.HasContractsNamespace = true;
                setting.HasIServicesNamespace = true;
                setting.HasServicesNamespace = true;
                Generator.Process.Instance.Execute(setting, GetDataBase(), ShowProcessProgress);                
            }
            catch (Exception ex)
            {
                MessageBox.Show("生成*.cs出现异常:" + ex.Message, "错误提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        #endregion
        /// <summary>
        /// 删除指定目录下所有文件
        /// </summary>
        private void DeleteAllFiles()
        {
            if (chkDeleteFiles.Checked)
            {
                try
                {
                    Directory.Delete(txtFolder.Text, true);
                }
                catch (Exception ex)
                { }
            }
        }

        private void btnOpenPath_Click(object sender, EventArgs e)
        {
            try
            {
                System.Diagnostics.Process.Start(this.txtFolder.Text);
            }
            catch (Exception ex)
            { }
        }
    }
}
